﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto;
using static Org.BouncyCastle.Math.EC.ECCurve;
using System.Xml;
using System.Text.RegularExpressions;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using System.Runtime.Serialization;
using System.Xml.Linq;
using NPOI.XSSF.Streaming.Values;

namespace EcoSystem
{
    /// <summary>
    /// 报表配置接口实现
    /// </summary>
    public class ReportConfigAppService : CrudAppService<
         ReportConfig,
         ReportConfigDto,
         Guid,
         GetReportConfigInput,
         CreateOrUpdateReportConfigDto,
         CreateOrUpdateReportConfigDto>, IReportConfigAppService
    {
        public IPermissionChecker PermissionChecker { get; private set; }

        public ReportConfigAppService(
            IRepository<ReportConfig, Guid> repository)
            : base(repository)
        {
            
        }

        public override async Task<ReportConfigDto> GetAsync(Guid id)
        {
            var result = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id);
            return MapToGetOutputDto(result);
        }

        /// <summary>
        /// 创建报表配置
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public override async Task<ReportConfigDto> CreateAsync(CreateOrUpdateReportConfigDto input)
        {
            if (string.IsNullOrEmpty(input.Name))
            {
                throw new UserFriendlyException("名称不能为空!");
            }
            if (string.IsNullOrEmpty(input.Code))
            {
                throw new UserFriendlyException("编码不能为空!");
            }
            if (input.ReportColumns == null || input.ReportColumns.Count == 0)
            {
                throw new UserFriendlyException("配置列不能为空!");
            }
            if (await (await Repository.GetQueryableAsync()).AnyAsync(x => x.Code == input.Code))
            {
                throw new UserFriendlyException("报表编码重复，指定的编码在系统中已存在!");
            }
            return await base.CreateAsync(input);
        }

        /// <summary>
        /// 更新报表配置
        /// </summary>
        /// <param name="id"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        public override async Task<ReportConfigDto> UpdateAsync(Guid id, CreateOrUpdateReportConfigDto input)
        {
            var report = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Id == id);
            if (report == null)
            {
                throw new UserFriendlyException("当前报表不存在");
            }
            if (string.IsNullOrEmpty(input.Name))
            {
                throw new UserFriendlyException("名称不能为空!");

            }
            if (string.IsNullOrEmpty(input.Code))
            {
                throw new UserFriendlyException("编码不能为空!");
            }
            if (input.ReportColumns == null || input.ReportColumns.Count == 0)
            {
                throw new UserFriendlyException("配置列不能为空!");
            }
            if (await (await Repository.GetQueryableAsync()).AnyAsync(x => x.Code == input.Code && x.Id != id))
            {
                throw new UserFriendlyException("报表编码重复，指定的编码在系统中已存在!");
            }
            return await base.UpdateAsync(id, input);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async override Task<PagedResultDto<ReportConfigDto>> GetListAsync(GetReportConfigInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.WhereIf(input.CategoryId.HasValue, x => x.CategoryId == input.CategoryId)
                .WhereIf(!string.IsNullOrWhiteSpace(input.Name), x => x.Name.Contains(input.Name) || x.Code.Contains(input.Name))
                .WhereIf(!string.IsNullOrWhiteSpace(input.Code), x => x.Code.Contains(input.Code))
                .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var totalCount = await query.CountAsync();
            var list = await query.OrderByDescending(x => x.CreationTime).PageBy(input.SkipCount, input.MaxResultCount).ToListAsync();
            return new PagedResultDto<ReportConfigDto>()
            {
                TotalCount = totalCount,
                Items = ObjectMapper.Map<List<ReportConfig>, List<ReportConfigDto>>(list)
            };
        }

        public async Task<ListResultDto<ReportConfigDto>> GetAllAsync(GetReportConfigInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.WhereIf(input.CategoryId.HasValue, x => x.CategoryId == input.CategoryId)
                .WhereIf(!string.IsNullOrWhiteSpace(input.Name), x => x.Name.Contains(input.Name) || x.Code.Contains(input.Name))
                .WhereIf(!string.IsNullOrWhiteSpace(input.Code), x => x.Code.Contains(input.Code))
                .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var list = await query.ToListAsync();
            var items = ObjectMapper.Map<List<ReportConfig>, List<ReportConfigDto>>(list);
            return new ListResultDto<ReportConfigDto>() { Items = items };
        }

        public async Task<ListResultDto<ReportConfigDto>> GetOwnsListAsync(bool onlyEnabled = true)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking();
            query = query.WhereIf(onlyEnabled, x => x.Status == onlyEnabled);
            var list = await query.ToListAsync();
            var items = ObjectMapper.Map<List<ReportConfig>, List<ReportConfigDto>>(list);
            return new ListResultDto<ReportConfigDto>() { Items = items };
        }

        public async Task<ReportConfigDto> GetForCodeAsync(string code)
        {
            var result = await (await Repository.GetQueryableAsync()).FirstOrDefaultAsync(x => x.Code == code && x.Status == true);
            if (result == null)
            {
                throw new UserFriendlyException("对应的报表查询配置信息不存在！");
            }
            return MapToGetOutputDto(result);
        }
    }
}
